package org.jeecg.modules.scm.service.impl;


import cfca.trustsign.demo.op.CfcaOp;
import cn.hutool.core.util.URLUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.commons.collections.map.HashedMap;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.exception.JeecgBootException;
import org.jeecg.common.system.api.ISysBaseAPI;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.common.util.CommonUtils;
import org.jeecg.common.util.RedisUtil;
import org.jeecg.common.vo.ScmResInfoVo;
import org.jeecg.common.vo.SysOrganizationVo;
import org.jeecg.modules.flow.api.FlowBaseCloudApi;
import org.jeecg.modules.flow.query.*;
import org.jeecg.modules.flow.vo.*;
import org.jeecg.modules.imm.api.ImmBaseCloudApi;
import org.jeecg.modules.scm.common.util.HttpRequest;
import org.jeecg.modules.scm.dto.BankLendingDto;
import org.jeecg.modules.scm.dto.BankReviewDto;
import org.jeecg.modules.scm.dto.BankReviewSendDto;
import org.jeecg.modules.scm.entity.*;
import org.jeecg.modules.scm.mapper.ScmFinaApplyMapper;
import org.jeecg.modules.scm.service.*;
import org.jeecg.modules.scm.vo.FinaApplyTaskVo;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.util.*;
/**
 * 1-未提交
 * 2-流程中
 * 3-已推送（资金端）
 * 4-待签约
 * 5-生效
 * 6-已放款
 * 7-作废
 * 8-否决
 * **/

/**
 * @Description: scm_fina_apply
 * @Author: jeecg-boot
 * @Date:   2021-11-10
 * @Version: V1.0
 */
@Service
public class ScmFinaApplyServiceImpl extends ServiceImpl<ScmFinaApplyMapper, ScmFinaApply> implements IScmFinaApplyService {
    /**
     * 流程调用api
     * */
    @Autowired
    private FlowBaseCloudApi flowBaseCloudApi;

    /**
     * 资金方项目关联接口
     * */
    @Autowired
    private IScmInvItemRsService iScmInvItemRsService;

    /**
     *云链单融资申请关联接口
     * */
    @Autowired
    private IScmChainFinaService iScmChainFinaService;
    /**
     *云链单融资申请合同关联接口
     * */
    @Autowired
    private IScmChainFinaContractService iScmChainFinaContractService;

    /**
     * 融资合同接口
     * */
    @Autowired
    private IScmFinaContractService iScmFinaContractService;

    /**
     * 客户信息接口
     * */
    @Autowired
    private IScmCusInfoService iScmCusInfoService;

    /**
     * 资金方接口
     * */
    @Autowired
    private IScmInvestorService iScmInvestorService;

    /**
     * 云链单债券凭证
     * */
    @Autowired
    private IScmCloudChainService iScmCloudChainService;

    /**
     * 系统模块api
     * */
    @Resource
    private ISysBaseAPI sysBaseAPI;

    /**报文模块API*/
    @Autowired
    private ImmBaseCloudApi immBaseCloudApi;

    @Autowired
    @Lazy
    private RedisUtil redisUtil;

    /**
     * 新增检查
     * */
    @Override
    public void check(ScmFinaApply scmFinaApply) {
        Date applyDate = scmFinaApply.getApplyDate();
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(new Date());
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        if(applyDate.before(calendar.getTime())){
            throw new JeecgBootException("申请放款日必须大于等于今天");
        }
        Date applyDdl = scmFinaApply.getApplyDdl();
    }

    /**
     * 检查对应申请是否存在
     * */
    @Override
    public ScmFinaApply checkApply(Integer applyNo) {
        ScmFinaApply scmFinaApply = baseMapper.selectById(applyNo);
        //TODO 此处默认未提交字典为0,后续修改
        if(scmFinaApply==null ){
            throw new JeecgBootException("没有该融资申请");
        }
        return scmFinaApply;
    }

    @Override
    public void updateFinaApply(Integer id, ScmFinaApply entity) {
        ScmFinaApply scmFinaApply = lambdaQuery().eq(ScmFinaApply::getApplyNo, id).one();
        if(scmFinaApply==null){
            throw new JeecgBootException("没有该融资申请");
        }
        entity.setApplyNo(id);
        baseMapper.updateById(entity);
    }

    /**
     * 上传附件
     * */
    @Override
    public String uploadAccessory(MultipartFile[] files, Integer applyNo) {
        if(files==null||files.length<=0){
            throw new JeecgBootException("未上传文件");
        }
        ScmFinaApply scmFinaApply = checkApply(applyNo);
        String urls = scmFinaApply.getAttachment();
        for(MultipartFile file:files){
            String url = CommonUtils.upload( file, "/finaApply", CommonConstant.UPLOAD_TYPE_MINIO);
            String path = URLUtil.getPath(url);
            if(!StringUtils.isNotBlank(path)) {
                continue;
            }
            if (StringUtils.isEmpty(urls)) {
                urls = path;
            } else {
                urls = urls + "," + path;
            }
        }
        scmFinaApply.setAttachment(urls);
        baseMapper.updateById(scmFinaApply);
        return urls;
    }

    //废弃
    @Override
    public List<ScmFinaApply> getApplyInfo() {
        LoginUser sysUser = SecurityUtils.getSubject().getPrincipal() != null ? (LoginUser) SecurityUtils.getSubject().getPrincipal() : null;
        if(sysUser==null){
            throw new JeecgBootException("用户信息获取失败");
        }
        return baseMapper.getApplyInfo(sysUser.getUsername());
    }

    /**
     * 获取待办任务
     * */
    @Override
    public List<FinaApplyTaskVo> getExecutableApplyInfo() {
        //获取当前用户id，流程api获取当前task
        TaskQuery query = new TaskQuery();
        query.setBusinessKey("apply-fina%");
        Result<Page<TaskVo>> result = flowBaseCloudApi.findTasks(query, 0, Integer.MAX_VALUE);
        if (result == null || !result.isSuccess() || result.getResult().getRecords().isEmpty()) {
            throw new JeecgBootException("任务为空");
        }
        List<FinaApplyTaskVo> res = new ArrayList<>();
        //得到任务，并从任务获取申请号，再将两者结合传回前端
        for (TaskVo task : result.getResult().getRecords()) {
            ProInstanceVo proInstance = flowBaseCloudApi.searchInstanceById(task.getInstanceId()).getResult();
            String applyNo = proInstance.getBusinessKey().split(":")[1];
            System.out.println("--------------" + applyNo);
            FinaApplyTaskVo taskVo = new FinaApplyTaskVo();
            BeanUtils.copyProperties(checkApply(Integer.parseInt(applyNo)), taskVo);
            taskVo.setTaskName(task.getTaskName());
            taskVo.setInstanceId(task.getInstanceId());
            taskVo.setTaskId(task.getTaskId());
            res.add(taskVo);
        }
        return res;

    }


    /**
     *资金方校验
     * * 获取项目关联资金方关联关系表信息
     * * 如果融资规模不足，则提示“校验不通过，当月剩余规模为***”；
     * * 检查申请日期是否在授信开始日、授信到期日之间，否则提示”申请日期不在授信日内“；
     * * 融资金额须小于单笔融资限额，否则提示”融资金额过大“；
     * * 融资期限小于单笔融资最大期限，大于单笔融资最小期限，否则”提示融资期限不在期限内“；
     * */
    @Override
    public boolean checkInvestor(Integer investorId, Integer itemId, BigDecimal amount, Date applyDate, Date endDate) {
        //用资金方项目关联表找到对应信息
        QueryWrapper<ScmInvItemRs> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda()
                .eq(ScmInvItemRs::getInvestorId,investorId)
                .eq(ScmInvItemRs::getItemId,itemId);
        ScmInvItemRs scmInvItemRs = iScmInvItemRsService.getOne(queryWrapper);
        if(scmInvItemRs==null){
            throw new JeecgBootException("未找到关联资金方信息");
        }
        if(scmInvItemRs.getMonthScaleLimit().subtract(scmInvItemRs.getUsedScale()).compareTo(amount)<0){
            throw new JeecgBootException("校验不通过，当月剩余规模为"+
                    scmInvItemRs.getMonthScaleLimit().subtract(scmInvItemRs.getUsedScale()));
        }
        if(applyDate.before(scmInvItemRs.getCreditStartTime())
                || applyDate.after(scmInvItemRs.getCreditEndTime())){
            throw new JeecgBootException("申请日期不在授信日内");
        }
        if(amount.compareTo(scmInvItemRs.getSingleFinLimit())>0){
            throw new JeecgBootException("融资金额过大");
        }
        int days = (int) ((endDate.getTime() - scmInvItemRs.getCreateTime().getTime()) / (1000 * 3600 * 24));
        if(days<Integer.parseInt(scmInvItemRs.getSingleFinMinTime())
                || days>Integer.parseInt(scmInvItemRs.getSingleFinMaxTime())
        ){
            throw new JeecgBootException("融资期限不在期限内");
        }
        return true;

    }

    /**
     * * 判断输入用户是否为平台，是的话需要检查《代客协议表》，是不是存在申请人客户签署的代客协议；否则输出**”平台无法代理客户提交申请“**
     * * 根据申请号applyNo获取融资申请信息，调用checkInvestor
     *
     * */
    @Override
    public boolean autoReview(String userId,Integer applyNo) {
        //TODO 完善自动审核代码 中登登记、工商查册、cfca信息填写
        System.out.println("-------------自动审核代码-------------");
        SysOrganizationVo result = sysBaseAPI.queryOrgByUserId(userId).getResult();
        if(result==null){
            throw new JeecgBootException("没有该用户");
        }
        //字典 1 是平台端
        if(result.getType()==1){
            System.out.println("平台端代理申请，检查代客协议");
            //TODO 代客协议，代客操作记录
            System.out.println("代客处理完毕");
        }
        //调用checkInvestor检查资金方
        ScmFinaApply scmFinaApply = checkApply(applyNo);
        return checkInvestor(scmFinaApply.getInvestorId(),
                scmFinaApply.getItemId(),
                scmFinaApply.getFinaAmount(),
                scmFinaApply.getApplyDate(),//融资申请日
                scmFinaApply.getApplyDdl());//融资到期日
//        if(conform){
//            //字典，此处1表示融资申请为未提交状态
//            scmFinaApply.setApplyState(1);
//            baseMapper.updateById(scmFinaApply);
//        }

    }


    /**
     *启动流程startInstance（客户号、机构号、业务种类、申请号数组）**，提交多条申请,
     * 此处默认业务种类为融资申请 apply-fina:key
     * */
    @Override
    public ScmResInfoVo startInstance(Integer[] applyNos) {
        //获取当前用户
        LoginUser sysUser = SecurityUtils.getSubject().getPrincipal() != null ?
                (LoginUser) SecurityUtils.getSubject().getPrincipal() : null;
        if(sysUser==null){
            throw new JeecgBootException("用户获取失败");
        }
        //TODO 固定业务种类为融资申请,此处写死
        String type = "apply-fina:";
        ScmResInfoVo scmResInfoVo = new ScmResInfoVo();
        List<String> success = new ArrayList<>();
        List<String> fail = new ArrayList<>();
        Map<String,String> message = new HashedMap();
        for(Integer applyNo:applyNos){
            try{
                boolean exists = iScmChainFinaService.lambdaQuery().eq(ScmChainFina::getApplyNo, applyNo).exists();
                if(!exists){
                    throw new JeecgBootException("融资申请未绑定云链单");
                }
                ScmFinaApply scmFinaApply = checkApply(applyNo);
                if(scmFinaApply.getApplyState()!=1){
                    throw new JeecgBootException("申请已被提交过");
                }
                //
                boolean conform = autoReview(sysUser.getId(),applyNo);
                //启动变量设置，流程匹配 核心企业、机构id、业务种类（包含申请的key）
                StartInstanceQuery startInstanceQuery = new StartInstanceQuery();
                startInstanceQuery.setName("融资申请");
                startInstanceQuery.setCusNo(scmFinaApply.getCoreCusNo());
                startInstanceQuery.setOrgId(sysUser.getOrganizationId());
                startInstanceQuery.setBusinessKey(type + applyNo.toString());
                startInstanceQuery.setVariables(new HashMap<>());
                String result = flowBaseCloudApi.startInstanceByProKey(startInstanceQuery).getResult();
                if(StringUtils.isBlank(result)){
                    throw new JeecgBootException("启动流程失败");
                }

                if(conform){
                    //TODO 字典，此处1表示融资申请为未提交状态,2流程中
                    scmFinaApply.setApplyState(2);
                    baseMapper.updateById(scmFinaApply);
                }
            }catch (Exception e){
                fail.add(applyNo.toString());
                message.put(applyNo.toString(),e.getMessage());
                continue;
            }
            success.add(applyNo.toString());

//            flowBaseCloudApi.startInstanceByProKey(StartInstanceQuery)
        }
        scmResInfoVo.setSuccess(success);
        scmResInfoVo.setFail(fail);
        scmResInfoVo.setMessage(message);
        return scmResInfoVo;
    }

    /**
     * 复核业务代码
     * */
    @Override
    public void reCheck(ScmFinaApply scmFinaApply) {
        //TODO 完善复核业务代码
        System.out.println("-------------平台复核业务代码-------------");

        //银行的url此处写死，我们应该可以根据资金方获取对应url链接
        /**
         * 银行端审批接口所需信息可以通过申请号绑定信息获取
         * （融资申请、云链单数字债权凭证、核心企业信息、CFCA、贸易合同、附件清单等）
         * **/
//        HttpRequest.PostInfomation("http://localhost:9999/jeecg-scm/test/jeecg/test",scmFinaApply);

        //封装要发送的信息
        //清单
        MultiValueMap<String, Object> params = new LinkedMultiValueMap<>();
        if(StringUtils.isNotBlank(scmFinaApply.getAttachment())){
            String[] files = scmFinaApply.getAttachment().split(".");
            for(String file:files){
                params.add("attachments",HttpRequest.getStreamResource(file));
            }
        }
        //基础贸易合同
        if(StringUtils.isNotBlank(scmFinaApply.getTradeContract()))
        {
            params.add("tradeContract",HttpRequest.getStreamResource(scmFinaApply.getTradeContract()));
        }

        //TODO 审批封装其他发送数据
        BankReviewSendDto bankReviewSendDto = new BankReviewSendDto();
        bankReviewSendDto.setScmCusInfo(iScmCusInfoService.getById(scmFinaApply.getCoreCusNo()));
        params.add("data",bankReviewSendDto);
//        HttpRequest.PostInfomation("http://212.64.69.165:9999/jeecg-scm/test/jeecg/test",params);
        //TODO 写死的url
        immBaseCloudApi.finaApplySend("http://212.64.69.165:9999/jeecg-scm/test/jeecg/test",params);
    }


    /**
     * 银行审批业务代码
     * */
    @Override
    public void bankReview(BankReviewDto bankReviewDto) {
        //TODO 完善银行审批业务代码
        System.out.println("-------------银行审批业务代码-------------");
        //将获取到的合同资料存入到对应申请号的融资合同当中（此处应该同时更新云链单融资合同关联表，文件已上传minio）
        //根据融资合同模板后端自动填充审批信息
        //将上述报文记录到资金方报文管理模块。
        //生成融资合同，从原始融资申请生成，并且使用返回数据修改,合同文件存储到合同附件中
        ScmFinaApply scmFinaApply = checkApply(bankReviewDto.getApplyNo());
        ScmFinaContract scmFinaContract = new ScmFinaContract();
        BeanUtils.copyProperties(scmFinaApply,scmFinaContract);
        BeanUtils.copyProperties(bankReviewDto,scmFinaContract);
        scmFinaContract.setContractNo(scmFinaApply.getCfca());
        if(iScmFinaContractService.getById(scmFinaApply.getApplyNo())!=null){
            iScmFinaContractService.removeById(scmFinaApply.getApplyNo());
        }
        //从redis获取合同文件路径,此时是模板合同
        scmFinaContract.setAttachment((String)redisUtil.get(scmFinaApply.getCfca()+"_path"));
        iScmFinaContractService.save(scmFinaContract);

        //填写云链单融资合同关联表
        List<ScmChainFina> list = iScmChainFinaService.lambdaQuery()
                .eq(ScmChainFina::getApplyNo, scmFinaApply.getApplyNo())
                .list();
        for(ScmChainFina scmChainFina:list){
            ScmChainFinaContract scmChainFinaContract = new ScmChainFinaContract();
            scmChainFinaContract.setApplyNo(scmFinaApply.getApplyNo());
            scmChainFinaContract.setChainNo(scmChainFina.getChainNo());
            scmChainFinaContract.setFinaContractNo(scmFinaContract.getContractNo());
            QueryWrapper<ScmChainFinaContract> queryWrapper = new QueryWrapper<>();
            queryWrapper.lambda().eq(ScmChainFinaContract::getChainNo,scmChainFinaContract.getChainNo())
                    .eq(ScmChainFinaContract::getFinaContractNo,scmChainFinaContract.getFinaContractNo());
            if(iScmChainFinaContractService.getOne(queryWrapper)!=null){
                iScmChainFinaContractService.remove(queryWrapper);
            }
            iScmChainFinaContractService.save(scmChainFinaContract);
        }


    }

    /**
     * 签约业务代码
     * */
    @Override
    public void cusSigning(String contractNo) {
        //TODO　完善签约业务代码
        System.out.println("-------------签约业务代码-------------");
        //签署合同
        String res = CfcaOp.signContractByKeyword(contractNo,(String)redisUtil.get(contractNo));
        //将签署的合同更新到minio上
        String path = (String) redisUtil.get(contractNo + "_path");
        String fileName = path.substring(path.lastIndexOf('\\')>=0?path.lastIndexOf('\\'):path.lastIndexOf('/') + 1);
        InputStream inputStream = CfcaOp.downloadContract(contractNo);
        CommonUtils.upload(inputStream,
                fileName,
                "/contractTemplate",
                CommonConstant.UPLOAD_TYPE_MINIO);
        //签约后删除redis缓存
        redisUtil.del(contractNo);
        redisUtil.del(contractNo+"_path");
        JSONObject jsonObject = JSONObject.parseObject(res);
        Map<String,Object> map = JSON.toJavaObject(jsonObject, Map.class);
        if(map.containsKey("errorCode")){
            throw new JeecgBootException(map.get("errorMessage").toString());
        }
        //TODO　通知核心企业、
        // 发送报文至银行端（应答报文）
        MultiValueMap<String, Object> params = new LinkedMultiValueMap<>();
        params.add("data","可以放款了");
//        HttpRequest.PostInfomation("http://212.64.69.165:9999/jeecg-scm/test/jeecg/test","可以放款了");
        //TODO 写死的url
        immBaseCloudApi.finaApplySend("http://212.64.69.165:9999/jeecg-scm/test/jeecg/test",params);
    }

    /**
     * 放款业务代码
     * */
    @Override
    public void lending(BankLendingDto bankLendingDto) {
        //TODO 完善放款业务代码
        System.out.println("银行已放款");
        /*
        * TODO
        *  云链单融资申请关联表的状态，云链单数字债券凭证状态为已融资？
        *   应收账款转让合同表；
        *  （根据云链单查找）更新应收账款信息表状态为“已融资”、收款账户信息（改为银行），融资申请表、状态更新为 生效；
        *  对于已经放款的业务，自动更新资金方关联关系表中的“已使用规模”、“已占用额度”；
        * */
        ScmFinaApply scmFinaApply = checkApply(bankLendingDto.getApplyNo());
        //5.已生效
//        scmFinaApply.setApplyState(5);
        //云链单融资申请关联表的状态
        iScmChainFinaService.lambdaUpdate().eq(ScmChainFina::getApplyNo,scmFinaApply.getApplyNo())
                //5关联表中是已放款，是字典，需修改
                .set(ScmChainFina::getState,5)
                .update();
        List<ScmChainFina> chainFinas = iScmChainFinaService.lambdaQuery()
                .eq(ScmChainFina::getApplyNo, scmFinaApply.getApplyNo()).list();
        for(ScmChainFina scmChainFina:chainFinas){
            iScmCloudChainService.lambdaUpdate().eq(ScmCloudChain::getChainNo,scmChainFina.getChainNo())
                    .set(ScmCloudChain::getStauts,5)
                    .update();
            redisUtil.del("cloud_chain_"+scmChainFina.getChainNo());
        }

//        //新增融资合同表,细节未修改，在审批阶段新增
//        ScmFinaContract scmFinaContract = new ScmFinaContract();
//        BeanUtils.copyProperties(scmFinaApply,scmFinaContract);
//        iScmFinaContractService.save(scmFinaContract);
//        应收账款待补充,应收账款转让合同表；
//        从资金方获取账户信息（废），应该是从银行发送信息获取
//        ScmInvestor investor = iScmInvestorService.getById(scmFinaApply.getInvestorId());
        // 更新应收账款信息表状态为“已融资”、收款账户信息（改为银行）
        List<ScmReceivables> receivables = baseMapper.getReceivables(scmFinaApply.getApplyNo());
        for(ScmReceivables receivable:receivables){
            //3代表已融资，结构表
            receivable.setStatus(3);
            //TODO 银行信息从何处获取，从银行所发送的信息中获取
        }
        //更新融资申请表
//        baseMapper.updateById(scmFinaApply);
        //已经放款的业务，自动更新资金方关联关系表中的“已使用规模”、“已占用额度”；
        ScmInvItemRs scmInvItemRs = iScmInvItemRsService.lambdaQuery()
                .eq(ScmInvItemRs::getInvestorId, scmFinaApply.getInvestorId())
                .eq(ScmInvItemRs::getItemId, scmFinaApply.getItemId())
                .one();
        iScmInvItemRsService.lambdaUpdate()
                .eq(ScmInvItemRs::getInvestorId,scmFinaApply.getInvestorId())
                .eq(ScmInvItemRs::getItemId,scmFinaApply.getItemId())
                //此处默认原大小加上融资金额
                .set(ScmInvItemRs::getUsedScale,scmInvItemRs.getUsedScale().add(scmFinaApply.getFinaAmount()))
                .set(ScmInvItemRs::getOccupiedQuota,scmInvItemRs.getOccupiedQuota().add(scmFinaApply.getFinaAmount()))
                .update();


    }

    /**
     * 通知业务代码
     * */
    @Override
    public void notice(String target) {
        //TODO 通知目标
        System.out.println("-------------通知目标-------------");
    }

    /**
     * 完成对应任务业务
     * submitType
     * 1 - 同意
     * 2 - 退回
     * 3 - 终结
     * 4 - 撤回
     * backType
     * 1.起点
     * 2.上一节点
     *
     * */
    @Override
    public void executeTask(String taskName,Integer applyNo,Integer submitType,Integer backType) {
        ScmFinaApply scmFinaApply = checkApply(applyNo);
        //TODO 根据任务名称执行对应任务
        //TODO 字典写死未对应
        System.out.println(taskName+"---------------------------");

        if(taskName.equals("复核")){
            if(submitType==1){
                if(scmFinaApply.getApplyState()!=2){
                    throw new JeecgBootException("当前不可复核");
                }
                //3是已推送
                scmFinaApply.setApplyState(3);
                reCheck(scmFinaApply);
            }
            //退回 含两种方式
            else if(submitType==2){
                if(scmFinaApply.getApplyState()!=2){
                    throw new JeecgBootException("非复核状态");
                }
                scmFinaApply.setApplyState(1);
                backOp(applyNo);
            }
            //撤回
            else if(submitType==4){
                throw new JeecgBootException("无法撤回起始");
//                if(scmFinaApply.getApplyState()!=2){
//                    throw new JeecgBootException("下一流程已被处理，当前无法撤回");
//                }
//                //撤回当前状态
//                scmFinaApply.setApplyState(2);


            }

        }
        else if(taskName.equals("审批")){

            //银行审批，该业务不在流程中，需有接受银行端报文的接口，并触发此函数
            //platformReview();
            if(submitType==1){
                if(scmFinaApply.getApplyState()!=3){
                    throw new JeecgBootException("当前不可审批");
                }
                //4是待签约
                scmFinaApply.setApplyState(4);
            }else if(submitType==2) {
                if(scmFinaApply.getApplyState()!=3){
                    throw new JeecgBootException("当前不可审批");
                }
                if(backType==1){
                    scmFinaApply.setApplyState(1);
                    backOp(applyNo);
                }else{
                    scmFinaApply.setApplyState(2);
                }
            }
            else if(submitType==4){
                if(scmFinaApply.getApplyState()!=4){
                    throw new JeecgBootException("下一流程已被处理，当前无法撤回");
                }
                scmFinaApply.setApplyState(3);
            }


        }
        else if(taskName.equals("签约")){
            //特判撤回
            if(submitType==4){
                if(scmFinaApply.getApplyState()==3){
                    scmFinaApply.setApplyState(2);
                }
                else{
                    throw new JeecgBootException("当前不可撤回");
                }
            }else{
                if(scmFinaApply.getApplyState()!=4){
                    System.out.println("当前状态为"+scmFinaApply.getApplyState());
                    throw new JeecgBootException("当前不可签约");
                }
                cusSigning(scmFinaApply.getCfca());
                scmFinaApply.setApplyState(5);
            }

        }
        else if(taskName.equals("放款")){
            //银行放款不在流程中，应在报文服务接口中触发此函数
            //6.已放款
            if(scmFinaApply.getApplyState()!=5){
                throw new JeecgBootException("融资未生效或已放款");
            }
            scmFinaApply.setApplyState(6);
            System.out.println(scmFinaApply);
        }
        else {
            System.out.println("没有业务执行");
        }
        if(submitType==3){
            //否决
            scmFinaApply.setApplyState(8);
            backOp(applyNo);
        }
        baseMapper.updateById(scmFinaApply);
    }

    /**
     * 完成对应任务
     * */

    @Override
    public Result<Boolean> processComplete(Integer applyNo, String comment, Integer submitType,Integer backType) {
        //TODO 融资的业务种类此处写死，后续考虑配置的方法
        String businessKey = "apply-fina:" + applyNo.toString();
        TaskVo task = flowBaseCloudApi.getActiveTaskByBusinessKey(businessKey);
//        if(!task.getTaskId().equals(taskId)&&submitType!=3){
//            throw new JeecgBootException("当前任务不存在");
//        }
        /*
         * 提交任务
         * 必须要传得参数: instanceId,taskId,comment
         * 可选择传得参数: variables,revocationType(撤回类型，撤回任务时需要传)
         * 需要指定提交类型：submitType：1同意、2退回、3终结、4、撤回上一节点
        * */
        SubmitTaskQuery taskQuery = SubmitTaskQuery.builder()
                .instanceId(task.getInstanceId())
                .taskId(task.getTaskId())
                .comment(comment)
                .submitType(submitType)
                .businessKey(businessKey)
                .backProcessType(backType)
                .build();


        //完成对应业务
        executeTask(task.getTaskName(),applyNo,submitType,backType);
        return flowBaseCloudApi.submitTask(taskQuery);

    }


    /**
     * 进度查询
     *
     * @return*/
    @Override
    public List<Map> processQuery(Integer applyNo, Integer pageNo, Integer pageSize) {
        //TODO 银行审批不在流程中，如何记录其相关操作，本地记录每次操作？
        //ProInstanceVo instance = flowBaseCloudApi.getInstanceByBusinessKey("apply-fina:" + applyNo.toString());
        HistoryInstanceQuery historyInstanceQuery = new HistoryInstanceQuery();
        historyInstanceQuery.setBusinessKey("apply-fina:" + applyNo.toString());
        Result<com.baomidou.mybatisplus.extension.plugins.pagination.Page<org.jeecg.modules.flow.vo.HistoryProcessInstanceVo>> pageResult = flowBaseCloudApi.queryHistoricProcessInstances(historyInstanceQuery, pageNo, pageSize);
        if(!pageResult.isSuccess()||pageResult.getResult()==null){
            throw new JeecgBootException("查询失败");
        }
        String instanceId = pageResult.getResult().getRecords().get(0).getId();
        System.out.println(instanceId);
        HistoryActivityQuery historyActivityQuery = new HistoryActivityQuery();
        historyActivityQuery.setProcessInstanceId(instanceId);

        Result<com.baomidou.mybatisplus.extension.plugins.pagination.Page<HistoryActivityInstanceVo>> Result = flowBaseCloudApi.queryHistoricActivityInstance(historyActivityQuery, pageNo, pageSize);
        List<HistoryActivityInstanceVo> records = Result.getResult().getRecords();
        List<Map> res = new ArrayList<>();
        for(HistoryActivityInstanceVo record : records){
            Field[] declaredFields = record.getClass().getDeclaredFields();
            Map<String,Object> map = new HashedMap();
            for(Field field:declaredFields){
                field.setAccessible(true);
                String fieldName = field.getName();
                Object value = null;
                try {
                    value = field.get(record);
                } catch (IllegalAccessException e) {
                    throw new JeecgBootException("进度获取失败");
                }
                map.put(fieldName, value);
            }
            String assignee = record.getAssignee();
            if(assignee!=null){
                System.out.println(assignee);
                String name = baseMapper.getUserOrg(assignee);
                map.put("assignee_name",name);
            }
            res.add(map);
        }

        return res;
    }

    /**
     * 回撤业务
     * */
    @Override
    public void backOp(Integer applyNo) {
        ScmFinaApply scmFinaApply = checkApply(applyNo);
        List<ScmChainFina> chainFinas = iScmChainFinaService.lambdaQuery()
                .eq(ScmChainFina::getApplyNo, scmFinaApply.getApplyNo()).list();
        for(ScmChainFina scmChainFina:chainFinas){
            ScmCloudChain scmCloudChain = iScmCloudChainService.lambdaQuery()
                    .eq(ScmCloudChain::getChainNo, scmChainFina.getChainNo())
                    .one();
            scmCloudChain.setStauts((Integer) redisUtil.get("cloud_chain_"+scmCloudChain.getChainNo()));
            redisUtil.del("cloud_chain_"+scmCloudChain.getChainNo());
            iScmCloudChainService.updateById(scmCloudChain);
        }
        iScmChainFinaService.lambdaUpdate()
                .eq(ScmChainFina::getApplyNo,applyNo)
                .remove();
        iScmChainFinaContractService.lambdaUpdate()
                .eq(ScmChainFinaContract::getApplyNo,applyNo)
                .remove();
    }
}
